import paho.mqtt.client as mqtt
import time
import json
import random

# OneNET MQTT配置
HOST = "183.230.40.96"
PORT = 1883
PRODUCT_ID = "F3i1fxm3zV" 
DEVICE_ID = "861556078753042"
ACCESS_KEY = "Mb0NIYXFr33Tee+37/1FXbthA+1BI+PvFY0twylPX28="

# 主题
TOPIC_PROPERTY_POST = f"$sys/{PRODUCT_ID}/{DEVICE_ID}/thing/property/post"
TOPIC_PROPERTY_POST_REPLY = f"$sys/{PRODUCT_ID}/{DEVICE_ID}/thing/property/post/reply"

# 设备连接token
TOKEN = "version=2018-10-31&res=products%2FF3i1fxm3zV%2Fdevices%2F861556078753042&et=2068172679&method=sha256&sign=VGZzMm%2FH54FM%2F3FTlDFgDxOryZqH4QwluKEHMo4VSkk%3D"

# 重连标志和次数计数
reconnect_flag = False
reconnect_count = 0
MAX_RECONNECT = 3

# 连接成功回调函数
def on_connect(client, userdata, flags, rc):
    print(f"连接结果: {rc}")
    global reconnect_flag, reconnect_count
    if rc == 0:
        print("连接成功！")
        reconnect_flag = False
        reconnect_count = 0
        # 订阅回复主题
        client.subscribe(TOPIC_PROPERTY_POST_REPLY)
        print(f"已订阅主题: {TOPIC_PROPERTY_POST_REPLY}")
    else:
        print("连接失败，返回码:", rc)

# 接收消息回调函数
def on_message(client, userdata, msg):
    print(f"收到消息 主题: {msg.topic}")
    print(f"消息内容: {msg.payload.decode('utf-8')}")

# 发布消息回调函数
def on_publish(client, userdata, mid):
    print(f"消息发布成功，消息ID: {mid}")

# 订阅回调函数
def on_subscribe(client, userdata, mid, granted_qos):
    print(f"订阅成功，消息ID: {mid}, QoS: {granted_qos}")

# 断开连接回调函数
def on_disconnect(client, userdata, rc):
    global reconnect_flag
    if rc != 0:
        print(f"意外断开连接，返回码: {rc}")
        reconnect_flag = True
    else:
        print("正常断开连接")

# 创建MQTT客户端实例
client = mqtt.Client(client_id=DEVICE_ID)

# 设置用户名和密码，OneNET平台用户名为产品ID，密码为token
client.username_pw_set(PRODUCT_ID, TOKEN)

# 设置回调函数
client.on_connect = on_connect
client.on_message = on_message
client.on_publish = on_publish
client.on_subscribe = on_subscribe
client.on_disconnect = on_disconnect

# 连接MQTT服务器
print(f"正在连接到 {HOST}:{PORT}...")
client.connect(HOST, PORT, keepalive=60)

# 启动网络循环
client.loop_start()

try:
    # 等待连接成功
    time.sleep(2)
    
    # 创建一个符合OneNet要求的测试消息，使用正确的属性标识符
    # 注意：根据onenet_data.h，温度应该是"temp"而非"temperature"
    test_data = {
        "id": f"123456",
        "version": "1.0",
        "params": {
            "temp": {"value": round(random.uniform(20, 30), 2)},
            "humidity": {"value": round(random.uniform(40, 70), 2)}
        }
    }
    
    # GPS坐标数据示例
    gps_data = {
        "id": "123457",
        "version": "1.0",
        "params": {
            "gps_lat": {"value": 39.9042},
            "gps_lon": {"value": 116.4074}
        }
    }
    
    # 发送温湿度数据
    payload = json.dumps(test_data)
    print(f"发布温湿度数据到主题: {TOPIC_PROPERTY_POST}")
    print(f"消息内容: {payload}")
    client.publish(TOPIC_PROPERTY_POST, payload, qos=1)
    
    # 等待回复
    print("等待温湿度数据回复中...")
    time.sleep(5)
    
    # 发送GPS数据
    payload = json.dumps(gps_data)
    print(f"发布GPS数据到主题: {TOPIC_PROPERTY_POST}")
    print(f"消息内容: {payload}")
    client.publish(TOPIC_PROPERTY_POST, payload, qos=1)
    
    # 等待回复
    print("等待GPS数据回复中...")
    time.sleep(5)
    
    # 保持连接并处理重连
    run_time = 0
    while run_time < 10:  # 最多运行10秒
        if reconnect_flag and reconnect_count < MAX_RECONNECT:
            print(f"尝试重连，第{reconnect_count + 1}次")
            try:
                client.reconnect()
                reconnect_count += 1
            except:
                print("重连失败")
        time.sleep(1)
        run_time += 1
        
except KeyboardInterrupt:
    print("程序被用户中断")

finally:
    # 断开连接
    client.loop_stop()
    client.disconnect()
    print("已断开连接")
